<?php

namespace Home\Controller;

use Think\Controller;
use Think\Log;
require_once dirname(__FILE__) . '/../../../../vendor/firebase/php-jwt/src/JWT.php';
require_once dirname(__FILE__) . '/../../../../vendor/firebase/php-jwt/src/Key.php';
require_once dirname(__FILE__) . '/../../../../vendor/firebase/php-jwt/src/SignatureInvalidException.php';
require_once dirname(__FILE__) . '/../../../../vendor/firebase/php-jwt/src/BeforeValidException.php';
require_once dirname(__FILE__) . '/../../../../vendor/firebase/php-jwt/src/ExpiredException.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

header("Content-type:text/html;charset=utf-8");

class CommonController extends Controller
{
    public function __construct()
    {
        parent::__construct();

        if (getenv('APP_DEBUG') == false) {
            // 测试阶段设置跨域
            // 设置能访问的域名
            $originarr = [
                'http://www.xiaoyaoji.cn',
                'http://xiaoyaoji.cn',
                'https://www.xiaoyaoji.cn',
                'https://xiaoyaoji.cn',
                'http://im.bjtxkj88.cn',
            ];
            // 获取当前跨域域名
            $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
            if (in_array($origin, $originarr)) {
                // 允许 $originarr 数组内的 域名跨域访问
                header('Access-Control-Allow-Origin:' . $origin);
                // 响应类型
                header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH');
                // 带 cookie 的跨域访问
                header('Access-Control-Allow-Credentials: true');
                // 响应头设置
                header('Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept, Authorization');
            }
            if($_SERVER['REQUEST_METHOD']=='OPTIONS'){
                //exit是用来结束程序执行的,如果参数是字符串，PHP将会直接把字符串输出，
                //如果参数是整型(范围是0-254)，那个参数将会被作为结束状态使用。
                exit('options类型的请求，结束');
            }
        }

        // 会员日记是否开启
        if (getenv('USER_LOG_RECORD')) {

            try {

                $request_param = I('param.');

                if(isset($request_param['user_id'])){
                    $param['user_id'] = $request_param['user_id'];
                }elseif(isset($request_param['userid'])){
                    $param['user_id'] = $request_param['userid'];
                }elseif(isset($request_param['data'])){
                    $jsonData = json_decode($request_param['data'], true);
                    if(!$jsonData){
                        $jsonData = json_decode(str_replace('&quot;','"', $request_param['data']), true);
                    }
                    if(isset($jsonData['user_id'])){
                        $param['user_id'] = $jsonData['user_id'];
                    }elseif(isset($jsonData['userid'])){
                        $param['user_id'] = $jsonData['userid'];
                    }
                }
  
                $user_listen = getenv('USER_LOG_LISTEN');

                if($user_listen){
                    if(!isset($param['user_id'])){
                        return;
                    }
                    $user_listen = explode(',',$user_listen);
                    if(!in_array($param['user_id'], $user_listen)){
                        return;
                    }
                }

                $param['request_url']      = 'apis/home/'.implode('/', I('path.'));
                $param['log_type']         = 3;
                $param['request_ip']       = $_SERVER["REMOTE_ADDR"];
                $param['request_param']    = sizeof($request_param) > 0 ? json_encode($request_param, JSON_UNESCAPED_UNICODE) : '';
                $param['request_method']   = REQUEST_METHOD;
                $param['time']      = time();

                M('user_request_log')->add($param);
                
            } catch (\Exception $e) {
                Log::write('记录请求错误：' . $e->getMessage(),'WARN');
            }
        }


        // 接口鉴权
        $request_url = 'apis/home/'.implode('/', I('path.'));
        if (strtolower($request_url) == strtolower('apis/home/Privatechat/addTalk')) {
            if ($_SERVER['REMOTE_ADDR'] != getenv('APP_HOST')) {
                $authorization = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
                $userData = $this->checkToken($authorization, false);
                if (!$userData) {
                    exit(json_encode(['code'=>402,'msg'=>'登录失效'], JSON_UNESCAPED_UNICODE));
                }
                if ($userData['data']['data']->userid != I('param.userid')) {
                    $this->ajaxReturn(['code'=>400, 'msg'=>'异常操作']);
                }
            }
        } else if (strtolower($request_url) == strtolower('apis/home/Dymanic/adddymanic')) {
            $authorization = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
            $userData = $this->checkToken($authorization);
        }
    }


    /**
     * 验证token是否有效,默认验证exp,nbf,iat时间
     * @param string $jwt 需要验证的token
     * @return string $msg 返回消息
     */
    private function checkToken($jwt, $exit = true){
        $key=getenv('JWT_KEY');
 
        try {
            JWT::$leeway = 60;//当前时间减去60，把时间留点余地
            $decoded = JWT::decode($jwt, new Key($key, 'HS256')); //HS256方式，这里要和签发的时候对应
            $arr = (array)$decoded;
 
 
            $returndata['status']="200";//200=成功
            $returndata['msg']="success";//
            $returndata['data']=$arr;//返回的数据
            return $returndata; //返回信息
 
        } catch(\Firebase\JWT\SignatureInvalidException $e) {  //签名不正确
            $returndata['code']="402";
            $returndata['status']="101";//101=签名不正确
            $returndata['msg']='登录失效';
            $returndata['msg_sys']=$e->getMessage();
            $returndata['data']="";//返回的数据
            if ($exit) {
                exit(json_encode($returndata)); //返回信息
            } else {
                return false;
            }
        } catch(\Firebase\JWT\BeforeValidException $e) {  // 签名在某个时间点之后才能用
            $returndata['code']="402";
            $returndata['status']="102";
            $returndata['msg']='登录失效';
            $returndata['msg_sys']=$e->getMessage();
            $returndata['data']="";//返回的数据
            if ($exit) {
                exit(json_encode($returndata)); //返回信息
            } else {
                return false;
            }
        } catch(\Firebase\JWT\ExpiredException $e) {  // token过期
            $returndata['code']="402";
            $returndata['status']="103";//103=签名不正确
            $returndata['msg']='登录失效';
            $returndata['msg_sys']=$e->getMessage();
            $returndata['data']="";//返回的数据
            if ($exit) {
                exit(json_encode($returndata)); //返回信息
            } else {
                return false;
            }
        } catch(\Exception $e) {  //其他错误
            $returndata['code']="402";
            $returndata['status']="199";//199=签名不正确
            $returndata['msg']='登录失效';
            $returndata['msg_sys']=$e->getMessage();
            $returndata['data']="";//返回的数据
            if ($exit) {
                exit(json_encode($returndata)); //返回信息
            } else {
                return false;
            }
        }
        //Firebase定义了多个 throw new，我们可以捕获多个catch来定义问题，catch加入自己的业务，比如token过期可以用当前Token刷新一个新Token
    }
}